﻿namespace FlexPlatform.BusinessLogic.Controllers
{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    
    using FlexPlatform.BusinessLogic.Validation;
    using FlexPlatform.Shared.Configuration;
    using FlexPlatform.Shared.DataModel;
    using FlexPlatform.DataModel;
    using FlexPlatform.Shared.Validation;
    using FlexPlatform.Common.Configuration;
    using FlexPlatform.Shared.Events;

    /// <summary>
    /// Contains the logic for all BusinesLogic associated to a property of any DataEntity.
    /// This covers: Validation, .
    /// </summary>
    public class PropertyController : IPropertyController
    {
        #region Private fields & Constructors

        /// <summary>
        /// The name of the controlled property.
        /// </summary>
        private string clsPropertyName;

        private IValidator clsValidator; 

        /// <summary>
        /// Creates a new instance of the <see cref="PropertyController"/>/>.
        /// </summary>
        /// <param name="propertyName"> The name of the controlled property.</param>
        public PropertyController(string propertyName, IEnumerable<IConfigurationElement> entityConfigurationElements)
        {
            this.clsPropertyName = propertyName;

            var validationRules = entityConfigurationElements.OfType<IPropertyValidationConfiguration>().Where(propVr => propVr.PropertyName == propertyName);

            ////clsValidator = new Validator(validationRules.Select(x => x.ValidationRule));
        }

        #endregion

        #region Raised Events

        /// <summary>
        /// Event raised after the completion of the validation process.
        /// </summary>
        public event EventHandler<PropertyValidationCompletedArgs> ValidationCompleted;

        #endregion

        /// <summary>
        /// Gets the name of the controlled property.
        /// </summary>
        public string PropertyName
        {
            get
            {
                return this.clsPropertyName;
            }
        }

        #region Private methods 

        /// <summary>
        /// Processes the "BeforePropertyChange" event.
        /// </summary>
        /// <param name="eventArgs"> The extra information related to the event.</param>
        internal void Process_OnBeforePropertyChange(BeforeProperyChangeEventArgs eventArgs)
        {            
            // This property (the controlled one) is about to change
            var validationResults = clsValidator.Validate(eventArgs.ProposedValue);
            
            // raise the event
            if (ValidationCompleted != null)
            {
                ValidationCompleted(this, new PropertyValidationCompletedArgs(this.PropertyName, validationResults));
            }

            // cancell the property update is the validation failed
            if (validationResults.Any(r => r.ValidationPassed == false))
            {
                eventArgs.RequestToCancel();
            }            
        }

        #endregion        
    }
}
